package com.zzjr.tools.java.ssm.factory;

import com.zzjr.tools.java.ssm.constants.AutoCodeConstants;
import com.zzjr.tools.java.ssm.utils.CamelUtils;
import com.zzjr.tools.java.ssm.utils.DBUtils;
import com.zzjr.tools.java.ssm.utils.IOUtils;
import com.zzjr.tools.java.ssm.utils.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Description: 实体类生成工程
 * 
 * @Date Create on 2015年10月13日
 * @author <a href="mailto:Aromarich@zuozh.com">Aromarich</a>
 * @since version1.0 Copyright 2015 ZZJR All Rights Reserved.
 */
public class ModelFactory {
	
	static private boolean f_util = true;
	
	static private boolean f_sql = false;
	
	static private String tableName;
	
	static private String authorName;
	
	static private String[] colnames;
	
	static private String[] colTypes;
	
	static private String[] colComments;
	
	// Java实体类文件路径
	static private File modelFile;
	
	// java model对象名
	static private String modelName;
	
	// 日期格式转换工具类
	static private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	
	/**
	 * 创建Model实体类文件
	 * 
	 * @throws IOException
	 */
	public static void generateModel(String tbName) throws IOException {
		System.out.println("开始生成Model实体类文件");
		tableName = tbName;
		modelName = StringUtils.upperFirstChar(CamelUtils.convertUnderLineToCamel(tableName));
		// 1.创建dataobject包
		String modelDir = AutoCodeConstants.PACKAGE_FULL_PATH + File.separator + "dataobject";
		IOUtils.mkDir(new File(modelDir));
		
		// 2.创建文件
		String filePath = modelDir + File.separator + modelName + ".java";
		modelFile = new File(filePath);
		IOUtils.createNewFile(modelFile);
		
		// 3.往Java文件中写入内容
		writeToJavaModelFile();
		System.out.println("完成Model实体类文件的生成");
	}
	
	/**
	 * 往Java文件中写入内容
	 * 
	 */
	private static void writeToJavaModelFile() {
		// 1根据表名获取字段属性
		authorName = AutoCodeConstants.AUTHOR_NAME;
		colnames = DBUtils.getColumnNameByTableName(tableName);
		colTypes = DBUtils.getColumnTypeByTableName(tableName);
		colComments = DBUtils.getColumnCommentByTableName(tableName);
		
		// 2.生成实体类主体代码
		StringBuilder content = parseModelFile();
		FileWriter fw;
		PrintWriter pw;
		try {
			fw = new FileWriter(modelFile);
			pw = new PrintWriter(fw);
			pw.println(content.toString());
			pw.flush();
			pw.close();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 功能：生成实体类主体代码
	 * 
	 * @return 返回拼装好的Java实体类主文件字符串内容
	 */
	private static StringBuilder parseModelFile() {
		StringBuilder sb = new StringBuilder();
		sb.append("package " + AutoCodeConstants.PACKAGE_NAME + ".dataobject" + ";\r\n\r\n");
		sb.append("import java.io.Serializable;\r\n\r\n");
		sb.append("import org.apache.commons.lang3.builder.ToStringBuilder;\r\n");
		sb.append("import org.apache.commons.lang3.builder.ToStringStyle;\r\n\r\n");
		// 判断是否导入工具包
		if (f_util) {
			sb.append("import java.util.Date;\r\n");
		}
		if (f_sql) {
			sb.append("import java.sql.*;\r\n");
		}
		sb.append("\r\nimport lombok.AllArgsConstructor;\r\n");
		sb.append("import lombok.Data;\r\n");
		sb.append("import lombok.NoArgsConstructor;\r\n");

		sb.append("\r\n");
		// 注释部分
		sb.append("/**\r\n");
		sb.append("* @Description:" + modelName + " 实体类\r\n");
		sb.append(" *\r\n");
		sb.append(" * @Date Create on " + sdf.format(new Date()) + "\r\n");
		sb.append(" * @author <a href=\"mailto:" + authorName + "@zuozh.com\">" + authorName + "</a>\r\n");
		sb.append(" * @since version1.0 Copyright 2018 ZZJR All Rights Reserved.\r\n");
		sb.append(" */\r\n");
		
		// 实体部分
		// 类名
		sb.append("\r\n@Data\r\n");
		sb.append("@NoArgsConstructor\r\n");
		sb.append("@AllArgsConstructor\r\n");
		sb.append("public class " + modelName + " implements Serializable {\r\n");
		processAllAttrs(sb);// 属性
		//processAllMethod(sb);// get set方法
		
		processToString(sb);// 添加toString()方法
		sb.append("}\r\n");
		
		return sb;
	}
	
	/**
	 * 功能：生成所有属性
	 * 
	 * @param sb
	 */
	private static void processAllAttrs(StringBuilder sb) {
		
		for (int i = 0; i < colnames.length; i++) {
			sb.append("\t/**\r\n");
			sb.append("\t*" + colComments[i] + "\r\n");
			sb.append("\t*/\r\n");
			sb.append("\tprivate " + sqlType2JavaType(colTypes[i]) + " "
					+ CamelUtils.convertUnderLineToCamel(colnames[i]) + ";\r\n\r\n");
		}
		sb.append("\t/**\r\n");
		sb.append("\t*分页对象\r\n");
		sb.append("\t*/\r\n");
		sb.append("\tprivate PageQuery pageQuery = new PageQuery();\r\n\r\n");
	}
	
	/**
	 * @Description：生成所有方法
	 * 
	 * @param sb
	 *            用于拼接内容的字符串
	 */
	private static void processAllMethod(StringBuilder sb) {
		
		for (int i = 0; i < colnames.length; i++) {
			sb.append("\tpublic void set" + StringUtils.upperFirstChar(CamelUtils.convertUnderLineToCamel(colnames[i]))
					+ "(" + sqlType2JavaType(colTypes[i]) + " " + CamelUtils.convertUnderLineToCamel(colnames[i])
					+ "){\r\n");
			sb.append("\t\tthis." + CamelUtils.convertUnderLineToCamel(colnames[i]) + "="
					+ CamelUtils.convertUnderLineToCamel(colnames[i]) + ";\r\n");
			sb.append("\t}\r\n\r\n");
			sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get"
					+ StringUtils.upperFirstChar(CamelUtils.convertUnderLineToCamel(colnames[i])) + "(){\r\n");
			sb.append("\t\treturn " + CamelUtils.convertUnderLineToCamel(colnames[i]) + ";\r\n");
			sb.append("\t}\r\n\r\n");
		}
	}
	
	/**
	 * @param sb
	 */
	private static void processToString(StringBuilder sb) {
		sb.append("\t@Override\r\n");
		sb.append("\tpublic String toString(){\r\n");
		sb.append("\t\treturn ToStringBuilder.reflectionToString(this,ToStringStyle.SHORT_PREFIX_STYLE);\r\n");
		sb.append("\t}\r\n\r\n");
	}
	
	/**
	 * 功能：获得列的数据类型
	 * 
	 * @param sqlType
	 * @return
	 */
	private static String sqlType2JavaType(String sqlType) {
		
		if (sqlType.equalsIgnoreCase("int")) {
			return "Integer";
		} else if (sqlType.equalsIgnoreCase("bigint")) {
			return "Long";
		} else if (sqlType.equalsIgnoreCase("tinyint")) {
			return "Integer";
		} else if (sqlType.equalsIgnoreCase("float")) {
			return "Float";
		} else if (sqlType.equalsIgnoreCase("double")) {
			return "Double";
		} else if (sqlType.equalsIgnoreCase("blob")) {
			return "byte[]";
		} else if (sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase("varchar")) {
			return "String";
		} else if (sqlType.equalsIgnoreCase("date") || sqlType.equalsIgnoreCase("datetime")
				|| sqlType.equalsIgnoreCase("timestamp")) {
			return "Date";
		}
		
		return "String";
	}
}
